import { Color, ImageAsset, Label, Node, Prefab, Sprite, SpriteFrame, UITransform, Vec3, find, instantiate, isValid, tween } from "cc";
import ResourcesManager from "./ResourcesManager";
import { EntityTypeEnum, G, GAttribute, IVec2, Singleton } from "../Common";
import { ObjectPoolManager } from "./ObjectPoolManager";
import { ExplosionManager } from "../Entity/Explosion/ExplosionManager";
import DataManager from "./DataManager";
import { GunFireManager } from "../Entity/GunFire/GunFireManager";
import { getIconBaseColor, getIconFrameColor } from "../Utils";
import { IPropConfig, ISkillConfig } from "../Common/common/Config";

export class MainManager extends Singleton {
    static get Ins() {
        return super.GetInstance<MainManager>()
    }
}

export const showToast = (str: string) => {
    ResourcesManager.Ins.loadRes('prefab/toast', Prefab).then((prefab) => {
        const node = instantiate(prefab)
        node.parent = find('Canvas')
        node.getComponentInChildren(Label).string = str
    })
}

/** 蓄力特效 */
export const castingTimeEffect = (node: Node) => {
    const sp = node.getComponent(Sprite)
    const color = new Color()
    color.set(255, 255, 255)
    const tw = tween(color)
        .to(G.CastingTime, { r: 255, g: 0, b: 255 }, {
            onUpdate: () => {
                if (isValid(node, true)) {
                    sp.color = color
                } else {
                    sp.color = Color.WHITE
                    tw.stop()
                }
            }
        })
        .call(() => {
            if (isValid(node, true)) {
                sp.color = Color.WHITE
            }
        })
        .start()

    tween(node)
        .by(G.CastingTime / 4 * 3, { scale: new Vec3(0, -0.1, 0), position: new Vec3(0, -12, 0) })
        .by(G.CastingTime / 4, { scale: new Vec3(0, 0.1, 0), position: new Vec3(0, 12, 0) })
        .start()
}

/** 添加命中效果，子弹爆炸 */
export const addExplosion = (position: IVec2) => {
    const node = ObjectPoolManager.Ins.poolAlloc(EntityTypeEnum.explosion)
    let em = node.getComponent(ExplosionManager)
    if (!em) {
        node.parent = DataManager.Ins.bm.bulletStage
        em = node.addComponent(ExplosionManager)
        em.init()
    }
    em.reset(position)
}

/** 添加开枪效果，枪口火焰 */
export const addGunFire = (parent: Node) => {
    const node = ObjectPoolManager.Ins.poolAlloc(EntityTypeEnum.gunFire)
    let em = node.getComponent(GunFireManager)
    if (!em) {
        em = node.addComponent(GunFireManager)
        em.init()
    }
    node.parent = parent
    em.reset()
}

/** 添加飘字 */
export const addLabel = (
    str: string | number,
    type: EntityTypeEnum.fontYellow | EntityTypeEnum.fontGreen | EntityTypeEnum.fontRed,
    { x, y }: IVec2
) => {
    const node = ObjectPoolManager.Ins.poolAlloc(type)
    node.parent = DataManager.Ins.bm.labelStage
    node.setPosition(x, y)
    node.getComponentInChildren(Label).string = '' + str
    tween(node)
        .by(0.2, { position: new Vec3(10 - Math.random() * 20, 20) })
        .by(0.2, { position: new Vec3(10 - Math.random() * 20, -20) })
        .by(0.01, { position: new Vec3(2) })
        .by(0.02, { position: new Vec3(-4) })
        .by(0.02, { position: new Vec3(4) })
        .by(0.02, { position: new Vec3(-4) })
        .by(0.02, { position: new Vec3(4) })
        .by(0.01, { position: new Vec3(-2) })
        .call(() => {
            ObjectPoolManager.Ins.poolFreeNode(type, node)
        })
        .start()
}

/** 闪白特效
 * @param node 
 * @param color 特效结束后的颜色，默认原色
 */
export const flash = (node: Node, color: Color = EntityShadeColor.Normal) => {
    const sprite = node.getComponent(Sprite)
    tween(node).stop()

    sprite.color = EntityShadeColor.Flash
    tween(node)
        .delay(0.05)
        .call(() => {
            sprite.color = color
        })
        .start()
}

/** entityShader的颜色，alpah的值为1时显示描边 */
export const EntityShadeColor = {
    /** 白色描边 */
    WhiteOutLine: new Color(255, 255, 255, 1),
    /** 绿色描边 */
    GreenOutLine: new Color(0, 255, 0, 1),
    /** 蓝色描边 */
    BlueOutLine: new Color(0, 0, 255, 1),
    /** 紫色描边 */
    PurpleOutLine: new Color(70, 0, 130, 1),
    /** 橙色描边 */
    OrangeOutLine: new Color(255, 69, 0, 1),
    /** 红色描边 */
    RedOutLine: new Color(255, 0, 0, 1),
    /** 闪白，纯白 */
    Flash: new Color(50, 255, 255, 255),
    /** 本来的颜色 */
    Normal: new Color(255, 255, 255, 255),
    /** 发红 */
    Red: new Color(0, 255, 255, 1),
    /** 白色透明 */
    WhiteOpacity: new Color(150, 150, 150, 50),
}

/** 获取物品icon */
export const getIcon = ({ entityType, star }): Promise<Node> => {
    return new Promise((resolve) => {
        ResourcesManager.Ins.loadRes('UIPrefab/IconNode', Prefab).then((prefab) => {
            const node = instantiate(prefab)
            const bg = node.getChildByName('bg').getComponent(Sprite)
            const frame = node.getChildByName('frame').getComponent(Sprite)
            const icon = node.getChildByName('icon').getComponent(Sprite)

            bg.color = new Color().fromHEX(getIconBaseColor(star))
            frame.color = new Color().fromHEX(getIconFrameColor(star))


            const setIcon = (imageAsset: ImageAsset) => {

                icon.spriteFrame = SpriteFrame.createWithImage(imageAsset);

                const uit = icon.node.getComponent(UITransform)
                const scale = uit.height > uit.width ? uit.height : uit.width

                const targetScale = node.getComponent(UITransform).height * 8 / 10
                icon.node.setScale(targetScale / scale, targetScale / scale)
            }

            ResourcesManager.Ins.loadRes('entityPng/' + entityType, ImageAsset).then((ia) => {
                if (isValid(node, true)) {
                    setIcon(ia)
                }
            }).catch(() => {
                ResourcesManager.Ins.loadRes('commonPng/default', ImageAsset).then((ia) => {
                    setIcon(ia)
                })
            })

            resolve(node)
        })
    })
}

export const getEquipAttrLabel = (k: string, v: string | number, parent: Node): Promise<Node> => {
    return new Promise((resolve) => {
        ResourcesManager.Ins.loadRes('UIPrefab/AttrLabel', Prefab).then((prefab) => {
            const node = instantiate(prefab)
            node.getChildByName('lab_k').getComponent(Label).string = k + ":"
            node.getChildByName('lab_v').getComponent(Label).string = '' + v
            node.parent = parent
            resolve(node)
        })
    })
}

export const getPropAttrLabel = (prop: IPropConfig, parent: Node): Promise<Node> => {
    return new Promise((resolve) => {
        ResourcesManager.Ins.loadRes('UIPrefab/AttrLabel', Prefab).then((prefab) => {
            const node = instantiate(prefab)
            const lab_v = node.getChildByName('lab_k').getComponent(Label)
            const lab_k = node.getChildByName('lab_v').getComponent(Label)
            lab_v.color = Color.GREEN
            lab_k.color = Color.WHITE

            lab_v.string = '+' + prop.attrValue
            lab_k.string = '' + GAttribute[prop.attrType].name

            node.parent = parent
            resolve(node)
        })
    })
}

export const getSkillDescLabel = (skill: ISkillConfig, parent: Node): Promise<Node> => {
    return new Promise((resolve) => {
        ResourcesManager.Ins.loadRes('UIPrefab/DescLabel', Prefab).then((prefab) => {
            const node = instantiate(prefab)
            const label = node.getComponent(Label)
            label.string = skill.skillDesc
            node.parent = parent
            resolve(node)
        })
    })
}